﻿// Copyright (c) 2011 Blue Onion Software, All rights reserved
using System;
using System.Collections.Generic;
using System.IO;
using BlueOnionSoftware.Bloget.Properties;
using BlueOnionSoftware.Bloget.Utility;

namespace BlueOnionSoftware.Bloget.Providers
{
    internal class XmlBlogProvider : BlogProvider
    {
        private const string NamespaceUri = "urn:blueonionsoftware-com:bloget:runtime:data";

        internal override Blog Load(string context)
        {
            Throw.IfNullOrEmpty(context, "path");

            var blog = File.Exists(context)
                ? Serializer.Load<Blog>(context, NamespaceUri)
                : CreateBlog(context);

            return blog;
        }

        internal override void Save(Blog blog, string context)
        {
            Serializer.Save<Blog>(context, NamespaceUri, blog);
        }

        internal override Content LoadContent(Guid id, string context)
        {
            Throw.IfEmpty(id, "id");
            Throw.IfNullOrEmpty(context, "path");
            string contentPath = null;
            Content content = null;

            try
            {
                contentPath = ResolvePostContentPath(id, context);
                content = Serializer.Load<Content>(contentPath, NamespaceUri);
            }

            catch (Exception ex)
            {
                content = new Content();
                content.Text = "Content \"" + contentPath + "\" " + ex.Message;
            }

            return content;
        }

        internal override void SaveContent(Guid id, Content content, string context)
        {
            Throw.IfEmpty(id, "id");
            Throw.IfNull(content, "content");
            Throw.IfNullOrEmpty(context, "path");

            var filename = ResolvePostContentPath(id, context);
            content.LastUpdate = DateTime.UtcNow;
            Serializer.Save<Content>(filename, NamespaceUri, content);
        }

        private Blog CreateBlog(string path)
        {
            if (File.Exists(path))
            {
                throw new InvalidOperationException("XmlBlogProvider: File already exists: " + path);
            }

            var blog = new Blog();
            blog.DataContext = path;

            var post = new Post();
            post.Title = Resources.BlogFirstPostTitle;

            var content = new Content();
            content.Text = Resources.Welcome.Replace("[post]", post.Id.ToString());
            blog.SaveContent(post.Id, content);

            blog.Posts.Add(post);
            blog.Save();
            return blog;
        }

        private string ResolvePostContentPath(Guid id, string path)
        {
            return Path.Combine(Path.GetDirectoryName(path), "C" + id + ".xml");
        }

        internal override void Backup(Blog blog, Stream stream)
        {
            Throw.IfNull(blog, "blog");
            Throw.IfNull(stream, "stream");

            // Using Environment.CurrentDirectory raises security exceptions in many
            // host providers so stick with the full paths.

            var directoryName = Path.GetDirectoryName(blog.DataContext);
            var files = new List<string>();
            files.Add(blog.DataContext);

            foreach (var post in blog.Posts)
            {
                files.Add(Path.Combine(directoryName, "C" + post.Id + ".xml"));
            }

            SimpleZip.ZipTo(files, stream, true);
        }
    }
}